﻿package com.bean.billtool;

import java.util.Calendar;
import java.util.Date;

public class CalcBill {

	private long     startSec;/*开始停车时间,ms*/
    private long     stopSec; /*结束停车时间,ms*/
	private int      dayStartHour; /*白天开始计费小时*/
	private int      dayStartMinute;/*白天开始计费分钟*/
	private int      dayStopHour; /*白天开始计费小时*/
	private int      dayStopMinute;/*白天开始计费分钟*/
	private int      nightStartHour; /*夜晚开始计费小时*/
	private int      nightStartMinute; /*夜晚开始计费分钟*/
	private int      nightStopHour; /*夜晚开始计费小时*/
	private int      nightStopMinute; /*夜晚开始计费分钟*/
	private double   dayUnit; /*白天计费单位时长*/
	private double   nightUnit; /*夜晚计费单位时长*/
	private double   dayPrice; /*白天计费单位单价*/
	private double   nightPrice;/*夜晚计费单位单价*/
	private int      igoreOverTime;/**一个计时单位内可以忽略的计费时长， 分钟计***/
	private int      igoreTime;     /*总时长小于这个则不收费，分钟计***/
	private int      crossDays = 0;

    //打印时间
	private void printTime(long  timex)
	{		
		Date date = new Date(timex);
		Calendar cal = Calendar.getInstance(); 
		cal.setTime(date); 
		System.out.println(String.format("%04d-%02d-%02d %02d:%02d:%02d ",
				          cal.get(Calendar.YEAR),
				          cal.get(Calendar.MONTH),
				          cal.get(Calendar.DAY_OF_MONTH),
				          cal.get(Calendar.HOUR_OF_DAY),
				          cal.get(Calendar.MINUTE),
				          cal.get(Calendar.SECOND)));
	}
	
	//获取一整天停车的费用
	private double getOneWholeDayPrice()
	{
		int   dayStart=  this.dayStartHour*3600 + this.dayStartMinute*60;
		int   dayStop =  this.dayStopHour*3600 + this.dayStopMinute*60;
		int   nightStart=  this.nightStartHour*3600 + this.nightStartMinute*60;
		int   nightStop =  this.nightStopHour*3600 + this.nightStopMinute*60;
		
		double dayHour = (double)((dayStop-dayStart)/3600.0);
		double nightHour;
		if (nightStart > nightStop) //跨天，如20：00-6：00
		{
			nightHour =  (double)((24*3600 - nightStart + nightStop) / 3600.0);
		}
		else 
		{
			nightHour = (double)((nightStop-nightStart)/3600.0);
		}
		
		int    daySec = (int)(dayHour / this.dayUnit);
		int    nightSec = (int)(nightHour / this.nightUnit);
		
		int dayRemainMin = (int) ((dayStop-dayStart)/60.0 - daySec*this.dayUnit*60);//剩余分钟数
		int nightRemainMin = (int) (nightHour*60.0 - nightSec*this.nightUnit*60);//剩余分钟数
//		System.out.println("dayRemainMin: "  + dayRemainMin + ", nightRemainMin: " + nightRemainMin);
		double dayRemainPrice = 0.0;
		double nightRemainPrice = 0.0;
		if (dayRemainMin > this.igoreOverTime)
		{
			dayRemainPrice = this.dayPrice;
		}
		if (nightRemainMin > this.igoreOverTime)
		{
			nightRemainPrice = this.nightPrice;
		}
		double oneDayPrice = daySec * this.dayPrice + dayRemainPrice;
		double oneNightPrice = nightSec * this.nightPrice + nightRemainPrice;

		System.out.println("oneWholeDayPrice: " + (float)(oneDayPrice+oneNightPrice) + ", crossdays: " + this.crossDays);
		return oneDayPrice+oneNightPrice;
	}
	
	//计算停车是否跨天，如果跨天，返回若干天的费用
	private double getAllWholeDayPrice()
	{
		long time = this.stopSec - this.startSec;
		int  day = (int)(time/(24*60*60*1000));
		this.crossDays = day;
		if (day > 0)
		{
			//停车满一天的全部费用
			double oneWholeDayPrice = getOneWholeDayPrice();
			return day*oneWholeDayPrice;
		}
		else
		{
			return 0.0;	
		}
	}
	
	//获取剩余不到一天的停车费用
	private double getRemainingPrice()
	{
		long newStartSec = this.startSec + this.crossDays*24*60*60*1000; //ms
		System.out.print("剩余时段开始时间： " ); printTime(newStartSec);
		System.out.print("剩余时段结束时间： " ); printTime(this.stopSec);
		
		Calendar c1 = Calendar.getInstance();
		c1.setTimeInMillis(newStartSec);

		Calendar c2 = Calendar.getInstance();
		c2.set(c1.get(Calendar.YEAR), c1.get(Calendar.MONTH), c1.get(Calendar.DAY_OF_MONTH), 
				this.dayStartHour, this.dayStartMinute);
		long dayStart = c2.getTimeInMillis();
//		System.out.print("白天计费开始时间： "); printTime(dayStart);

		Calendar c3 = Calendar.getInstance();
		c3.set(c1.get(Calendar.YEAR), c1.get(Calendar.MONTH), c1.get(Calendar.DAY_OF_MONTH), 
				this.dayStopHour, this.dayStopMinute);
		long dayStop = c3.getTimeInMillis();
//		System.out.print("白天计费结束时间： "); printTime(dayStop);
		
		Calendar c4 = Calendar.getInstance();
		c4.set(c1.get(Calendar.YEAR), c1.get(Calendar.MONTH), c1.get(Calendar.DAY_OF_MONTH), 
				this.nightStartHour, this.nightStartMinute);
		long nightStart = c4.getTimeInMillis();
//		System.out.print("晚上计费开始时间： "); printTime(nightStart);
		
		Calendar c5 = Calendar.getInstance();
		c5.set(c1.get(Calendar.YEAR), c1.get(Calendar.MONTH), c1.get(Calendar.DAY_OF_MONTH), 
				this.nightStopHour, this.nightStopMinute);
		long nightStop = c5.getTimeInMillis();
		if (nightStart > nightStop)
		{
			nightStop = nightStop + 24*60*60*1000;
		}
//		System.out.print("晚上计费结束时间： "); printTime(nightStop);//可能为第二天时间
		
		long previousNightStart = nightStart - 24*60*60*1000;
//		System.out.print("前一天晚上计费开始时间： "); printTime(previousNightStart);
		
		long previousNightStop = nightStop - 24*60*60*1000;
//		System.out.print("前一天晚上计费结束时间： "); printTime(previousNightStop);
		
		
		long nextDayStart = dayStart + 24*60*60*1000;
//		System.out.print("下一天白天计费开始时间： "); printTime(nextDayStart);
		
		long nextDayStop = dayStop + 24*60*60*1000;
//		System.out.print("下一天白天计费结束时间： "); printTime(nextDayStop);
		
		long nextNightStart = nightStart + 24*60*60*1000;
//		System.out.print("下一天晚上计费开始时间： "); printTime(nextNightStart);
		
		long nextNightStop = nightStop + 24*60*60*1000;
//		System.out.print("下一天晚上计费结束时间： "); printTime(nextNightStop);
		
		int dayMinute = 0;
		int nightMinute = 0;
		//以分钟为单位累加白天和夜晚的计费总时间
		while(newStartSec < this.stopSec)
		{
			if ((newStartSec >= previousNightStart)&&(newStartSec < previousNightStop))
			{
				nightMinute++;
			}
			if ((newStartSec >= dayStart)&&(newStartSec < dayStop))
			{
				dayMinute++;
			}
			if ((newStartSec >= nightStart)&&(newStartSec < nightStop))
			{
				nightMinute++;
			}
			if ((newStartSec >= nextDayStart)&&(newStartSec < nextDayStop))
			{
				dayMinute++;
			}
			if ((newStartSec >= nextNightStart)&&(newStartSec < nextNightStop))
			{
				nightMinute++;
			}
			newStartSec = newStartSec + 60*1000;
		}

		if (((dayMinute + nightMinute) < this.igoreTime)&&(this.crossDays == 0))
		{
			return 0.0;
		}
			
		int    severalDayUnit = (int)((double)(dayMinute/60.0) / this.dayUnit);
		int    severalNightUnit = (int)((double)(nightMinute/60.0) / this.nightUnit);
		
		int dayRemainMin = (int) (dayMinute - severalDayUnit*this.dayUnit*60);//剩余分钟数
		int nightRemainMin = (int) (nightMinute - severalNightUnit*this.nightUnit*60);//剩余分钟数
		System.out.println("dayRemainMin: "  + dayRemainMin + ", nightRemainMin: " + nightRemainMin);
		double dayRemainPrice = 0.0;
		double nightRemainPrice = 0.0;
		if (dayRemainMin > this.igoreOverTime)
		{
			dayRemainPrice = this.dayPrice;
		}
		if (nightRemainMin > this.igoreOverTime)
		{
			nightRemainPrice = this.nightPrice;
		}
		double dayPrice = (double)(severalDayUnit*this.dayPrice) + dayRemainPrice;
		double nightPrice = (double)(severalNightUnit*this.nightPrice) + nightRemainPrice;
		System.out.println("remaining:dayPrice=" + dayPrice + ", nightPrice=" + nightPrice);
		
		double totalRemainingPrice = dayPrice + nightPrice;
		return totalRemainingPrice;
	}
	
	//计费
	public float  calc_park_bill( long     startSec/*开始停车时间*/,
                                  long     stopSec /*结束停车时间*/,
                                  int      dayStartHour, /*白天开始计费小时*/
                                  int      dayStartMinute,/*白天开始计费分钟*/
                                  int      dayStopHour, /*白天开始计费小时*/
                                  int      dayStopMinute,/*白天开始计费分钟*/
                                  int      nightStartHour, /*夜晚开始计费小时*/
                                  int      nightStartMinute, /*夜晚开始计费分钟*/
                                  int      nightStopHour, /*夜晚开始计费小时*/
                                  int      nightStopMinute, /*夜晚开始计费分钟*/
                                  double   dayUnit, /*白天计费单位时长*/
                                  double   nightUnit, /*夜晚计费单位时长*/
                                  double   dayPrice, /*白天计费单位单价*/
                                  double   nightPrice,/*夜晚计费单位单价*/
                                  double   gratuity, /***小费**/
                                  int      igoreOverTime,/**一个计时单位内可以忽略的计费时长， 分钟计***/
                                  int      igoreTime     /*总时长小于这个则不收费，分钟计***/
								  )
	{
		//入参打印
		System.out.print("start time: ");  printTime(startSec);
		System.out.print("stop  time: ");  printTime(stopSec);
		System.out.println(String.format("day   start[%02d:%02d] -- stop [%02d:%02d] ",dayStartHour,dayStartMinute,dayStopHour,dayStopMinute));
		System.out.println(String.format("night start[%02d:%02d] -- stop [%02d:%02d] ",nightStartHour,nightStartMinute,nightStopHour,nightStopMinute));
		System.out.println(String.format("dayUnit:   %.2f,  dayPrice:   %.2f", dayUnit,dayPrice));
		System.out.println(String.format("nightUnit: %.2f,  nightPrice: %.2f", nightUnit,nightPrice));
		System.out.println(String.format("gratuity:        %.2f", gratuity));
		System.out.println(String.format("iIgoreOverTime:  %d",igoreOverTime));
		System.out.println(String.format("time < %d minute price is 0 ",igoreTime));
		System.out.println("----------------------------------------------------------------------------");
		
		this.startSec = startSec;
		this.stopSec = stopSec;
		this.dayStartHour = dayStartHour;
		this.dayStartMinute = dayStartMinute;
		this.dayStopHour = dayStopHour;
		this.dayStopMinute = dayStopMinute;
		this.nightStartHour = nightStartHour;
		this.nightStartMinute = nightStartMinute;
		this.nightStopHour = nightStopHour;
		this.nightStopMinute = nightStopMinute;
		this.dayUnit = dayUnit;
		this.nightUnit = nightUnit;
		this.dayPrice = dayPrice;
		this.nightPrice = nightPrice;
		this.igoreOverTime = igoreOverTime;
		this.igoreTime = igoreTime;
		
		double     totalPrice = 0.0f;
		
		//计算停车是否跨天，如果跨天，返回若干天的费用
		totalPrice = getAllWholeDayPrice();
		
		//计算剩余不到一天的费用
		totalPrice = totalPrice + getRemainingPrice();
				
		System.out.println(String.format("total price = %.2f ",totalPrice));
		totalPrice = totalPrice + gratuity;	
		System.out.println(String.format("total price + Gratuity =  %.2f", totalPrice));
		System.out.println("------------------------------------------------");
		
		return (float) totalPrice;
	}
	
	public long get_time_t(int nYear,int Month,int nDay,int nHour,int nMinute,int nSecond)
	{
		Calendar cal = Calendar.getInstance(); 
		cal.set(nYear, Month, nDay, nHour, nMinute, nSecond);
		long  timex = cal.getTime().getTime(); 
		return timex;
	}
	
	public static void main(String[] args) 
	{
		long   tTimeStart;
		long   tTimeStop;
		
		CalcBill c1 = new CalcBill();
	    tTimeStart =  c1.get_time_t(2014,8,1,22,0,0);
	    tTimeStop =   c1.get_time_t(2014,8,2,21,0,0);
		c1.calc_park_bill(tTimeStart,tTimeStop,8,00,18,0,20,0,8,00,0.25,0.5,2.0,3.0,5.00,5,10);


	}

}
